#include <atlimage.h>
#include "Raytracer.cu"
#include "Triangle.cu"

int3 toRGB(float3 flt){
	int3 ret;
	ret.x = (int)(flt.x*255);
	ret.y = (int)(flt.y*255);
	ret.z = (int)(flt.z*255);
	return ret;
}

//Kernels can be left untouched. 
__global__ void ptrKernel(Triangle* tri, int* n) {

	for (int iter = 0; iter < *n; iter++) {
		tri[iter].print();
	}
}

__global__ void VertKernel(Vertex* v) {
	v->print();
	v->loc = Vector3(1.9f, 4.5f, 8.3f);
	v->print();
}

void vertHelper(Vertex& vert){
	if(vert.d_address == NULL){
		vert.copyToDevice();
		cudaStreamSynchronize(NULL);
	}
	VertKernel<<<1,1>>>((Vertex*)vert.d_address);
	cudaStreamSynchronize(NULL);
}

void renderPixelsWrapper(RenderArgs* args, Scene* scene){
	dim3 blocks(args->imageResolution.x,args->imageResolution.y);
	dim3 threads(1);

	if(args->d_address == NULL){
		args->copyToDevice();
	}
	if(scene->d_address == NULL){
		scene->copyToDevice();
	}

	renderPixel<<<blocks, threads>>>((RenderArgs*)args->d_address, (Scene*)scene->d_address);
	cudaDeviceSynchronize();
	args->updateFromDevice();
	scene->updateFromDevice();
	cudaDeviceSynchronize();
}

int main (int argc, char* argv[]) {
	CImage img;
	img.Load("test.png");
	//Begin setting render arguments
	RenderArgs args = RenderArgs();
	int w = 300;
	int h = 300;
	args.imageResolution = make_int2(w, h);
	args.imageData = new float3[w*h];
	args.background = Vector3(0.5f, 0.1f, 0.7f);
	args.sampleResolution = make_int2(1, 1);
	//Begin making scene
	Scene* scene = Scene::getTestScene();
	//copy args and scene to device
	args.copyToDevice();
	scene->copyToDevice();
	//render
	renderPixelsWrapper(&args, scene);
	for(int y = 0; y<h; y++){ 	
		for(int x = 0; x < w; x++){
			int idx = y*300 + x;
			int3 rgb = toRGB(args.imageData[idx]);
			img.SetPixelRGB(x, y, rgb.x, rgb.y, rgb.z);
		}
	}
	img.Save("test_save.png");
	system("pause");
	return 0;
}